package com.opensource.component.query.matedata;

import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.opensource.component.query.exception.MpExtendException;
import com.opensource.component.query.sharding.TableSharding;
import com.opensource.component.query.sharding.TableShardingStrategy;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ZonLen since on 2021/12/26 下午3:05
 */
public final class TableMetadataHelper {

  private static final Map<Class<?>, TableMetadata> TABLE_METADATA_MAP = new HashMap<>();

  private static final Map<Class<?>, String> GLOBAL_TABLE_NAME = new HashMap<>();

  public static void addTableMetadata(TableMetadata tableMetadata) {
    final Class<?> tableClass = tableMetadata.getTableInfo().getEntityType();
    TABLE_METADATA_MAP.put(tableClass, tableMetadata);
    GLOBAL_TABLE_NAME.putIfAbsent(tableClass, globalTableSharding(tableClass));
  }

  public static TableMetadata tableMetadata(Class<?> tableClass) {
    final TableMetadata tableMetadata = TABLE_METADATA_MAP.get(tableClass);
    if (null == tableMetadata) {
      throw new MpExtendException("Non exist table class[" + tableClass.getName() + "]");
    }
    return tableMetadata;
  }

  private static String tableName(Class<?> tableClass) {
    return tableMetadata(tableClass).getTableName();
  }

  public static String tableAlias(Class<?> tableClass) {
    return tableMetadata(tableClass).getAlias();
  }

  public static String globalFinalTableName(Class<?> tableClass) {
    return GLOBAL_TABLE_NAME.get(tableClass);
  }

  /**
   * 全局的分库分表进行缓存
   */
  private static String globalTableSharding(Class<?> tableClass) {
    final TableSharding tableSharding = tableClass.getAnnotation(TableSharding.class);
    if (tableSharding != null) {
      try {
        final TableShardingStrategy tableShardingStrategy = tableSharding.sharding().newInstance();
        return finalTableName(tableClass, tableShardingStrategy);
      } catch (InstantiationException | IllegalAccessException e) {
        throw new MpExtendException("Class[" + tableClass.getName()
            + "] @TableSharding(sharding = TableShardingStrategy.class) annotation Cannot be instantiated for ["
            + tableSharding.sharding().getName() + "] by non param constructor method");
      }
    }
    return tableName(tableClass);
  }

  /**
   * 自定义的获取查询表结果
   */
  public static String finalTableName(Class<?> tableClass,
      TableShardingStrategy tableShardingStrategy) {
    final String databaseName = tableShardingStrategy.dataBaseName();
    final String tableName = tableName(tableClass);
    if (StringUtils.isNotBlank(databaseName)) {
      return Constants.BACKTICK + databaseName + Constants.BACKTICK + Constants.DOT
          + Constants.BACKTICK + tableShardingStrategy.shardingTableName(tableName)
          + Constants.BACKTICK;
    } else {
      return Constants.BACKTICK + tableShardingStrategy.shardingTableName(tableName)
          + Constants.BACKTICK;
    }
  }
}
